package com.hzncc.flowable_diboot.service.refundmanage.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.diboot.core.binding.Binder;
import com.diboot.core.binding.QueryBuilder;
import com.diboot.core.holder.ThreadLocalHolder;
import com.diboot.core.util.V;
import com.diboot.core.vo.Pagination;
import com.diboot.iam.entity.BaseLoginUser;
import com.diboot.iam.util.IamSecurityUtils;
import com.diboot.notification.config.Cons;
import com.diboot.notification.entity.Message;
import com.hzncc.flowable_diboot.constans.ContractModelKeyConstants;
import com.hzncc.flowable_diboot.contract.entity.ContractInfo;
import com.hzncc.flowable_diboot.contract.entity.SalesContract;
import com.hzncc.flowable_diboot.contract.service.ContractAuditService;
import com.hzncc.flowable_diboot.contract.service.ContractInfoService;
import com.hzncc.flowable_diboot.contract.service.SalesContractService;
import com.hzncc.flowable_diboot.contract.vo.ContractInfoDetailVO;
import com.hzncc.flowable_diboot.contract.vo.SalesContractListVO;
import com.hzncc.flowable_diboot.dto.refundmanage.RefundContractDTO;
import com.hzncc.flowable_diboot.entity.SapCustomer;
import com.hzncc.flowable_diboot.entity.invoicemanage.InvoiceRegister;
import com.hzncc.flowable_diboot.entity.refundmanage.RefundRegister;
import com.hzncc.flowable_diboot.entity.refundmanage.SapRefundContract;
import com.hzncc.flowable_diboot.enums.RegisterTypeEnum;
import com.hzncc.flowable_diboot.exception.BusinessException;
import com.hzncc.flowable_diboot.payment.entity.OldReceive;
import com.hzncc.flowable_diboot.payment.entity.PaymentContract;
import com.hzncc.flowable_diboot.payment.entity.PaymentRegister;
import com.hzncc.flowable_diboot.payment.entity.SapPaymentContract;
import com.hzncc.flowable_diboot.payment.service.OldReceiveService;
import com.hzncc.flowable_diboot.payment.vo.OldReceiveListVO;
import com.hzncc.flowable_diboot.payment.vo.PaymentContractListVO;
import com.hzncc.flowable_diboot.payment.vo.SapPaymentContractDetailVO;
import com.hzncc.flowable_diboot.payment.vo.SapPaymentContractListVO;
import com.hzncc.flowable_diboot.rabbitmq.service.impl.SendMessageService;
import com.hzncc.flowable_diboot.service.SapCustomerService;
import com.hzncc.flowable_diboot.service.bpm.BpmProcessDefinitionService;
import com.hzncc.flowable_diboot.service.bpm.BpmProcessInstanceService;
import com.hzncc.flowable_diboot.service.bpm.BpmProcessTaskService;
import com.hzncc.flowable_diboot.service.invoicemanage.InvoiceRegisterService;
import com.hzncc.flowable_diboot.service.refundmanage.RefundRegisterService;
import com.hzncc.flowable_diboot.service.refundmanage.SapRefundContractService;
import com.hzncc.flowable_diboot.util.ConstantUtil;
import com.hzncc.flowable_diboot.util.MessageCons;
import com.hzncc.flowable_diboot.vo.bpm.BpmProcessInstanceCreateReqVO;
import com.hzncc.flowable_diboot.vo.bpm.BpmTaskApproveReqVO;
import com.hzncc.flowable_diboot.vo.refundmanage.RefundContractDetailVO;
import com.hzncc.flowable_diboot.vo.refundmanage.RefundContractListVO;
import com.hzncc.flowable_diboot.vo.refundmanage.SapRefundContractDetailVO;
import com.hzncc.flowable_diboot.vo.refundmanage.SapRefundContractListVO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.diboot.core.util.S;
import com.diboot.core.service.impl.BaseServiceImpl;

import com.hzncc.flowable_diboot.entity.refundmanage.RefundContract;

import com.hzncc.flowable_diboot.mapper.refundmanage.RefundContractMapper;
import com.hzncc.flowable_diboot.service.refundmanage.RefundContractService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
* 合同退款 相关Service实现类
* @author MyName
* @version 1.0
* @date 2024-11-11
* Copyright © MyCorp
*/
@Slf4j
@Service
public class RefundContractServiceImpl extends BaseServiceImpl<RefundContractMapper, RefundContract> implements RefundContractService {

    @Resource
    private SapRefundContractService sapRefundContractService;

    @Resource
    private BpmProcessDefinitionService bpmProcessDefinitionService;

    @Resource
    private BpmProcessInstanceService bpmProcessInstanceService;

    @Resource
    private BpmProcessTaskService bpmProcessTaskService;

    @Resource
    private SalesContractService salesContractService;

    @Resource
    private InvoiceRegisterService invoiceRegisterService;

    @Resource
    private SendMessageService sendMessageService;

    @Resource
    private SapCustomerService sapCustomerService;

    @Resource
    private OldReceiveService oldReceiveService;

    @Resource
    private RefundRegisterService refundRegisterService;

    @Resource
    private ContractAuditService contractAuditService;

    @Resource
    private ContractInfoService contractInfoService;

    @Override
    public List<SapRefundContractListVO> getSapRefundContract(String sapCustomerId) {
//        Map<String,List<SapRefundContractListVO>> result = new HashMap<>();
        LambdaQueryWrapper<SalesContract> salesContractQuery = new LambdaQueryWrapper<>();
        salesContractQuery.eq(SalesContract::getSoldToParty,sapCustomerId).in(SalesContract::getPaymentStatus,2,3) //查询部分收款和已收款的sap合同
                .eq(SalesContract::isDeleted,0)
                .eq(SalesContract::getPushStatus, 1); // 只带回推送成功的销售合同
        List<SalesContract> entityList = salesContractService.getEntityList(salesContractQuery);
        List<SalesContractListVO> salesContractListVOS = Binder.convertAndBindRelations(entityList, SalesContractListVO.class);
        List<SapRefundContractListVO> sapRefundContractListVOList = new ArrayList<>();
//        List<SapRefundContractListVO> sapInvoicedRefundContractListVOS = new ArrayList<>();
//        List<SapRefundContractListVO> sapNoInvoicedRefundContractListVOS = new ArrayList<>();
        for (SalesContractListVO salesContractListVO : salesContractListVOS){
            SapRefundContractListVO sapRefundContractListVO = new SapRefundContractListVO();
            sapRefundContractListVO.setContractCode(salesContractListVO.getOrderCode()); // 采购订单编号
            sapRefundContractListVO.setSapContractCode(salesContractListVO.getSapCode()); // sap合同号
            sapRefundContractListVO.setTotalAmount(new BigDecimal(StringUtils.isNotEmpty(salesContractListVO.getFixedDiscountAmount())?salesContractListVO.getFixedDiscountAmount():"0")); // 合同总金额
            sapRefundContractListVO.setReceivedAmount(new BigDecimal(StringUtils.isNotEmpty(salesContractListVO.getAmountReceived())?salesContractListVO.getAmountReceived():"0")); // 已收款金额
            if (StringUtils.isNotEmpty(salesContractListVO.getAmountNotReceived())){
                sapRefundContractListVO.setUnpaidAmount(new BigDecimal(salesContractListVO.getAmountNotReceived()));
            }else {
                sapRefundContractListVO.setUnpaidAmount(sapRefundContractListVO.getTotalAmount().subtract(sapRefundContractListVO.getReceivedAmount()));
            }
            sapRefundContractListVO.setSalesEmployeeId(salesContractListVO.getSalesEmployee());
            sapRefundContractListVO.setSalesEmployeeName(salesContractListVO.getSalesEmployeeLabel());
            sapRefundContractListVO.setSalesArea(salesContractListVO.getSalesTerritory());
            if (StringUtils.isEmpty(salesContractListVO.getProjectContractId())){
                sapRefundContractListVO.setReviewCategory("0");
            }else {
                sapRefundContractListVO.setReviewCategory("1");
            }
            sapRefundContractListVOList.add(sapRefundContractListVO);
            LambdaQueryWrapper<InvoiceRegister> invoiceRegisterQuery = new LambdaQueryWrapper<>();
            invoiceRegisterQuery.eq(InvoiceRegister::getSapContractCode,salesContractListVO.getSapCode()).in(InvoiceRegister::getRegisterType, RegisterTypeEnum.normal.getCode(),RegisterTypeEnum.abnormal.getCode());
            List<InvoiceRegister> invoiceRegisterList = invoiceRegisterService.getEntityList(invoiceRegisterQuery);
            if (CollectionUtils.isEmpty(invoiceRegisterList)){
                sapRefundContractListVO.setInvoicedAmount(new BigDecimal(0));
//                sapNoInvoicedRefundContractListVOS.add(sapRefundContractListVO);
            }else {
                BigDecimal invoiceAmountTotal = invoiceRegisterList.stream().map(InvoiceRegister::getInvoiceAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                if (invoiceAmountTotal.compareTo(new BigDecimal(0))<=0){
                    sapRefundContractListVO.setInvoicedAmount(new BigDecimal(0));
                }
                sapRefundContractListVO.setInvoicedAmount(invoiceAmountTotal);
//                sapInvoicedRefundContractListVOS.add(sapRefundContractListVO);
            }
        }
//        result.put("invoiced",sapInvoicedRefundContractListVOS);
//        result.put("noInvoiced",sapNoInvoicedRefundContractListVOS);
        return sapRefundContractListVOList;
    }

    @Override
    public OldReceiveListVO getOldReceive(String sapCustomerId) {
        //查询客户的老应收
        OldReceiveListVO oldReceiveListVO = new OldReceiveListVO();
        oldReceiveListVO.setReceivableAmount(new BigDecimal(0)).setReceivedAmount(new BigDecimal(0)).setUnreceivedAmount(new BigDecimal(0));
        SapCustomer sapCustomer = sapCustomerService.getEntity(sapCustomerId);
        if(ObjectUtils.isNotEmpty(sapCustomer)){
            String sapNo = sapCustomer.getSapNo();
            String companyCode = sapCustomer.getCompanyCode();
            LambdaQueryWrapper<OldReceive> oldReceiveQuery = new LambdaQueryWrapper<>();
            oldReceiveQuery.eq(OldReceive::getCompanyCode,companyCode).eq(OldReceive::getSapNo,sapNo).eq(OldReceive::isDeleted,0);
            ThreadLocalHolder.setIgnoreInterceptor();
            OldReceive oldReceive = oldReceiveService.getSingleEntity(oldReceiveQuery);
            if (ObjectUtils.isNotEmpty(oldReceive)){
                oldReceiveListVO = Binder.convertAndBindRelations(oldReceive, OldReceiveListVO.class);
            }
        }

        return oldReceiveListVO;
    }

    @Override
    public List<RefundContractListVO> getRefundContractList(RefundContractDTO queryDto, Pagination pagination) {
        if (StringUtils.isNotEmpty(queryDto.getSapCustomerName())){
            LambdaQueryWrapper<SapCustomer> sapCustomerQuery = new LambdaQueryWrapper<>();
            sapCustomerQuery.like(SapCustomer::getName, "%" + queryDto.getSapCustomerName()+ "%");
            List<SapCustomer> entityList = sapCustomerService.getEntityList(sapCustomerQuery);
            List<String> collect = entityList.stream().map(SapCustomer::getId).collect(Collectors.toList());
            queryDto.setSapCustomerIds(collect);
            queryDto.setSapCustomerName(null);
        }
        QueryWrapper<RefundContract> queryWrapper = QueryBuilder.toQueryWrapper(queryDto);
        if (pagination != null && V.isEmpty(pagination.getOrderBy())) {
            pagination.setOrderBy(Pagination.ORDER_BY_ID_DESC);
        }

        return this.getViewObjectList(queryWrapper, pagination, RefundContractListVO.class);
    }

    @Override
    @Transactional
    public Boolean createRefundContract(RefundContractDetailVO refundContract) {
        if (StringUtils.isEmpty(refundContract.getRefundRegisterId())){
            throw new BusinessException("退款登记不存在");
        }
        RefundRegister refundRegister = refundRegisterService.getEntity(refundContract.getRefundRegisterId());
        if (ObjectUtils.isEmpty(refundRegister)){
            throw new BusinessException("退款登记不存在");
        }
        BigDecimal noReturnAmount = refundRegister.getNoReturnAmount();
        if (noReturnAmount.compareTo(new BigDecimal(0))<=0){
            throw new BusinessException("当前退款登记已全部退款,无法再进行合同退款");
        }
        refundContract.setProcessState("1");
        this.createEntity(refundContract);
        String sapCustomerId = refundContract.getSapCustomerId();
        String sapCustomerCode = refundContract.getSapCustomerCode();
        refundRegister.setSapCustomerId(sapCustomerId);
        refundRegister.setCustomerCode(sapCustomerCode);
        refundRegisterService.updateEntity(refundRegister);
        List<SapRefundContractDetailVO> sapRefundContractDetailVOList = refundContract.getSapRefundContractList();
        Map<String,Object> variables = new HashMap<>();
        variables.put("hasSapPayment","0");
        if (!CollectionUtils.isEmpty(sapRefundContractDetailVOList)){
            sapRefundContractDetailVOList = sapRefundContractDetailVOList.stream().peek(item->{
                item.setRefundContractId(refundContract.getId());
                item.setReceivedAmount(item.getReceivedAmount().subtract(item.getCurrentRefundAmount()));
                item.setUnpaidAmount(item.getTotalAmount().subtract(item.getReceivedAmount()));
            }).collect(Collectors.toList());
            sapRefundContractService.createEntities(sapRefundContractDetailVOList);
            variables.put("hasSapPayment","1");
        }
        String instanceId = this.createContractProcessInstance(ContractModelKeyConstants.REFUND_CONTRACT_SUBMIT, refundContract.getId(),variables);
        refundContract.setInstanceId(instanceId);
        this.updateEntity(refundContract);
        bpmProcessTaskService.commitUserTask(instanceId);
        return true;
    }

    @Override
    @Transactional
    public Boolean updateRefundContract(RefundContractDetailVO refundContract) {
        if (StringUtils.isEmpty(refundContract.getRefundRegisterId())){
            throw new BusinessException("退款登记不存在");
        }
        RefundRegister refundRegister = refundRegisterService.getEntity(refundContract.getRefundRegisterId());
        if (ObjectUtils.isEmpty(refundRegister)){
            throw new BusinessException("退款登记不存在");
        }
        BigDecimal noReturnAmount = refundRegister.getNoReturnAmount();
        if (noReturnAmount.compareTo(new BigDecimal(0))<=0){
            throw new BusinessException("当前退款登记已全部退款,无法再进行合同退款");
        }
        refundContract.setProcessState("1");
        String sapCustomerId = refundContract.getSapCustomerId();
        String sapCustomerCode = refundContract.getSapCustomerCode();
        refundRegister.setSapCustomerId(sapCustomerId).setCustomerCode(sapCustomerCode);
        refundRegisterService.updateEntity(refundRegister);
        LambdaQueryWrapper<SapRefundContract> sapRefundContractQuery = new LambdaQueryWrapper<>();
        sapRefundContractQuery.eq(SapRefundContract::getRefundContractId,refundContract.getId());
        sapRefundContractService.deleteEntities(sapRefundContractQuery);
        List<SapRefundContractDetailVO> sapRefundContractDetailVOList = refundContract.getSapRefundContractList();
        Map<String,Object> variables = new HashMap<>();
        variables.put("hasSapPayment","0");
        if (!CollectionUtils.isEmpty(sapRefundContractDetailVOList)){
            sapRefundContractDetailVOList = sapRefundContractDetailVOList.stream().peek(item->{
                item.setId(null);
                item.setRefundContractId(refundContract.getId());
                item.setReceivedAmount(item.getReceivedAmount().subtract(item.getCurrentRefundAmount()));
                item.setUnpaidAmount(item.getTotalAmount().subtract(item.getReceivedAmount()));
            }).collect(Collectors.toList());
            sapRefundContractService.createEntities(sapRefundContractDetailVOList);
            variables.put("hasSapPayment","1");
        }
        variables.put("approve","1");
        BpmTaskApproveReqVO approveReqVO = new BpmTaskApproveReqVO();
        approveReqVO.setId(refundContract.getTaskId());
        approveReqVO.setReason("审批通过");
        approveReqVO.setVariables(variables);
        bpmProcessTaskService.approveTask(approveReqVO);
        this.updateEntity(refundContract);
        return true;
    }

    @Override
    public Boolean updateRefundContractStatus(String id, String status) {
        LambdaUpdateWrapper<RefundContract> refundContractUpdate = new LambdaUpdateWrapper<>();
        refundContractUpdate.set(RefundContract::getProcessState,status).eq(RefundContract::getId,id);
        return this.update(refundContractUpdate);
    }

    public String createContractProcessInstance(String modelKey, String businessKey,Map<String,Object> variables) {
        String processDefinitionId = bpmProcessDefinitionService.getBpmProcessDefinitionIdByKey(modelKey);
        BpmProcessInstanceCreateReqVO bpmProcessInstanceCreateReqVO = new BpmProcessInstanceCreateReqVO();
        bpmProcessInstanceCreateReqVO.setProcessDefinitionId(processDefinitionId).setBusinessKey(businessKey).setVariables(variables);
        return bpmProcessInstanceService.createProcessInstance(bpmProcessInstanceCreateReqVO);
    }
}